if (typeof org == 'undefined') {
	var org = {};
}
if (typeof org.gcarreno == 'undefined') {
	org.gcarreno = {};
}

org.gcarreno.jSapiens = {
	_mainURL: "http://api.stackoverflow.com/",
	_apiVer: "1.0",
	_key: "[PLEASE CHANGE ME!]",
	
	_req: Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]  
		  .createInstance(Components.interfaces.nsIXMLHttpRequest),
	
	_console: Components.classes['@mozilla.org/consoleservice;1']
			  .getService(Components.interfaces.nsIConsoleService),
			  
	init: function(){
		this.Log('init()');
		this.answers._parent = this;
		this.questions._parent = this;
		this.users._parent = this;
		return 0;
	},
	API: {
		User: "/users",
		UserQuestions: "",
		UserAnswers: "",
		UserFavorites: "",
		UserReputation: "",
		UserRecent: "",
		UserFlair: ""
	},
	
	answers: {
		_parent: null,
		find: function(answerList) {
			this._parent.Log('answers.find(' + answerList + ')');
			var text = null;
			if (answerList != 0 || answerList != null) {
				var url = this._parent._mainURL + this._parent._apiVer + "/answers/" + answerList;
				if (text = this._parent.Get(url)){
					return this._parent.JSONDecode(text);
				}
			}
			return this._parent.JSONDecode("{[]}");
		},
		comments: function(anserList) {
			this._parent.Log('answers.comments(' + answerList + ')');
			var text = null;
			if (answerList != 0 || answerList != null) {
				var url = this._parent._mainURL + this._parent._apiVer + "/answers/" + answerList + '/comments';
				if (text = this._parent.Get(url)){
					return this._parent.JSONDecode(text);
				}
			}
			return this._parent.JSONDecode("{[]}");
		}
	},
	
	questions: {
		_parent: null,
		find: function(questionList) {
			this._parent.Log('questions.find(' + questionList + ')');
			var text = null;
			if (questionList != 0 || questionList != null) {
				var url = this._parent._mainURL + this._parent._apiVer + "/questions/" + questionList;
				if (text = this._parent.Get(url)){
					return this._parent.JSONDecode(text);
				}
			}
			return this._parent.JSONDecode("{[]}");
		},
		answers: function(questionList) {
			this._parent.Log('questions.answers(' + questionList + ')');
			var text = null;
			if (questionList != 0 || questionList != null) {
				var url = this._parent._mainURL + this._parent._apiVer + "/questions/" + questionList + '/answers';
				if (text = this._parent.Get(url)){
					return this._parent.JSONDecode(text);
				}
			}
			return this._parent.JSONDecode("{[]}");
		}
	},
	
	users: {
		_parent: null,
		find: function(userList){
			this._parent.Log('users.find(' + userList + ')');
			return this._parent.JSONDecode("{[]}");
		},
		answers: function(userList){
			this._parent.Log('users.answers(' + userList + ')');
			return this._parent.JSONDecode("{[]}");
		},
		timeline: function (userList){
			this._parent.Log('users.timeline(' + userList + ')');
			var text = null;
			if (userList != 0 || userList != null) {
				var url = this._parent._mainURL + this._parent._apiVer + "/users/" + userList + '/timeline';
				if (text = this._parent.Get(url)){
					return this._parent.JSONDecode(text);
				}
			}
			return this._parent.JSONDecode("{[]}");
		}
	},
	
	Get: function(url){
		this.Log('Get: "' + url + '"');
		this._req.open('GET', url, false);
		this._req.send(null);
		
		if (this._req.status == 200) {
			return this._req.responseText;
		}
		return 0;
	},
	
	JSONDecode: function(json){
			var JSON = Components.classes["@mozilla.org/dom/json;1"]
						.createInstance(Components.interfaces.nsIJSON);
						
			return JSON.decode(json);
	},
	
	Log: function (aMessage) {
		this._console.logStringMessage('jSapiens: ' + aMessage);
	}
}

org.gcarreno.StackOverflowBar = {
	searchHistory: Components.classes["@mozilla.org/satchel/form-history;1"]
				   .getService(Components.interfaces.nsIFormHistory2 || Components.interfaces.nsIFormHistory),
	_first_run: null,
	JSON: null,
	Preferences: null,
	Strings: {
		Constants: {
			Protocol: "http",
			Host: "stackoverflow.com",
			Ask: "/questions/ask",
			Home: {
				Active: "/?tab=active",
				Featured: "/?tab=featured",
				Hot: "/?tab=hot",
				Week: "/?tab=week",
				Month: "/?tab=month"
			},
			Questions: {
				Newest: "/questions?sort=newest",
				Featured: "/questions?sort=featured",
				Hot: "/questions?sort=hot",
				Votes: "/questions?sort=votes",
				Active: "/questions?sort=active"					
			},
			UnAnswered: {
				MyTags: "/unanswered/tagged?tab=mytags",
				Newest: "/unanswered/tagged?tab=newest",
				Votes: "/unanswered/tagged?tab=votes"
			},
			User: {
				Stats: "/users/%s?tab=stats#tab-top",
				Activity: "/users/%s?tab=activity#tab-top",
				Reputation: "/users/%s?tab=reputationhistory#tab-top",
				Favorites: "/users/%s?tab=favorites#tab-top",
				Preferences: "/users/%s?tab=preferences#tab-top",
				Accounts: "/users/%s?tab=accounts#tab-top",
				
				Recent: "/users/recent/%s?tab=summary#tab-top",
				RecentRep: "/users/recent/%s?tab=reputation#tab-top",
				Responses: "/users/recent/%s?tab=responses#tab-top",
				Revisions: "/users/recent/%s?tab=revisions#tab-top",
				Badges: "/users/recent/%s?tab=badges#tab-top"
			}
		},
		Buttons: {
			Search: "button_search",
			Ask: "button_ask",
			TabActive: "button_tab_active",
			TabFeatured: "button_tab_featured",
			TabHot: "button_tab_hot",
			TabWeek: "button_tab_week",
			TabMonth: "button_tab_month",
			Featured: "button_featured",
			New: "button_new",
			Hot: "button_hot",
			Votes: "button_votes",
			Active: "button_active",
			TabMyTags: "button_tab_mytags",
			TabNewest: "button_tab_newest",
			TabVotes: "button_tab_votes",
			UserStats: "button_user_stats",
			UserActivity: "button_user_actvity",
			UserReputation: "button_user_reputation",
			UserFavorites: "button_user_favorites",
			UserPreferences: "button_user_preferences",
			UserAccounts: "button_user_accounts",
			
			UserRecentSummary: "button_user_recent_summary",
			UserRecentReputation: "button_user_recent_reputation",
			UserRecentResponses: "button_user_recent_responses",
			UserRecentRevisions: "button_user_recent_revisions",
			UserRecentBadges: "button_user_recent_badges",
			ShowOptions: "button_show_options",
			ShowOverview: "button_show_overview"
		},
		Options: {
			SearchInTab: "search_in_tab",
			ButtonsInTab: "buttons_in_tab",
			UserID: "user_id"
		}
	},
	Search: function (event, type) {
		this.Utils.Log('Entering Search: ' + type);
		var URL = "";
		var isEmpty = false;
		var searchTerms = this.Utils.TrimString(this.GetTerms());
		if (searchTerms.length == 0) {
			isEmpty = true;
		} else {
			this.searchHistory.addEntry("SOB-SearchTerms-History", searchTerms);
			searchTerms = this.Utils.ConvertTermsToURI(searchTerms);
		}
	
		switch(type)
		{
			case "sob_search":
				if(!isEmpty) {
					URL = this.Strings.Constants.Protocol + "://" + 
						  this.Strings.Constants.Host + "/search?q=" + 
						  searchTerms;
				}
				break;
		}
		if (!isEmpty) {
			this.Utils.LoadURL(URL, this.Utils.GetOption(this.Strings.Options.SearchInTab, "bool"));
		}
	},
	SearchTermsTextEntered: function (param){
		this.Utils.Log('Entering SearchTermsTextEntered');
		this.Search(null, 'sob_search');
	},
	GetTerms: function () {
		this.Utils.Log('Entering GetTerms');
		var terms = document.getElementById("SOB-SearchTerms");
		return terms.value;
	},
	SetTerms: function (newTerms) {
		this.Utils.Log('Entering SetTerms');
		var terms = document.getElementById("SOB-SearchTerms");
		terms.value = newTerms;
	},
	ButtonClick: function (buttonName) {
		this.Utils.Log('Entering ButtonClick: ' + buttonName);
		
		const buttons = this.Strings.Buttons;
		const consts = this.Strings.Constants;
		const homepage = consts.Home;
		const questions = consts.Questions;
		const unanswered = consts.UnAnswered;
		const user = consts.User;
		const opts = this.Strings.Options;
		
		var loadURL = this.Utils.LoadURL;
		
		var inNewTab = this.Utils.GetOption(opts.ButtonsInTab, "bool");
		var userID = this.Utils.GetOption(opts.UserID, "string");
		
		switch (buttonName) {
			case buttons.Ask:
				loadURL(consts.Protocol + "://" +
						consts.Host + consts.Ask, inNewTab);
				break;
			case buttons.TabActive:
				loadURL(consts.Protocol + "://" +
						consts.Host + homepage.Active, inNewTab);
				break;
			case buttons.TabFeatured:
				loadURL(consts.Protocol + "://" +
						consts.Host + homepage.Featured, inNewTab);
				break;
			case buttons.TabHot:
				loadURL(consts.Protocol + "://" +
						consts.Host + homepage.Hot, inNewTab);
				break;
			case buttons.TabWeek:
				loadURL(consts.Protocol + "://" +
						consts.Host + homepage.Week, inNewTab);
				break;
			case buttons.TabMonth:
				loadURL(consts.Protocol + "://" +
						consts.Host + homepage.Month, inNewTab);
				break;
			case buttons.New:
				loadURL(consts.Protocol + "://" +
						consts.Host + questions.Newest, inNewTab);
				break;
			case buttons.Featured:
				loadURL(consts.Protocol + "://" +
						consts.Host + questions.Featured, inNewTab);
				break;
			case buttons.Hot:
				loadURL(consts.Protocol + "://" +
						consts.Host + questions.Hot, inNewTab);
				break;
			case buttons.Votes:
				loadURL(consts.Protocol + "://" +
						consts.Host + questions.Votes, inNewTab);
				break;
			case buttons.Active:
				loadURL(consts.Protocol + "://" +
						consts.Host + questions.Active, inNewTab);
				break;
			case buttons.TabMyTags:
				loadURL(consts.Protocol + "://" +
						consts.Host + unanswered.MyTags, inNewTab);
				break;
			case buttons.TabNewest:
				loadURL(consts.Protocol + "://" +
						consts.Host + unanswered.Newest, inNewTab);
				break;
			case buttons.TabVotes:
				loadURL(consts.Protocol + "://" +
						consts.Host + unanswered.Votes, inNewTab);
				break;
			case buttons.UserStats:
				loadURL(consts.Protocol + "://" +
						consts.Host + this.Utils.sprintf(user.Stats, userID), inNewTab);
				break;
			case buttons.UserActivity:
				loadURL(consts.Protocol + "://" +
						consts.Host + this.Utils.sprintf(user.Activity, userID), inNewTab);
				break;
			case buttons.UserReputation:
				loadURL(consts.Protocol + "://" +
						consts.Host + this.Utils.sprintf(user.Reputation, userID), inNewTab);
				break;
			case buttons.UserFavorites:
				loadURL(consts.Protocol + "://" +
						consts.Host + this.Utils.sprintf(user.Favorites, userID), inNewTab);
				break;
			case buttons.UserPreferences:
				loadURL(consts.Protocol + "://" +
						consts.Host + this.Utils.sprintf(user.Preferences, userID), inNewTab);
				break;
			case buttons.UserAccounts:
				loadURL(consts.Protocol + "://" +
						consts.Host + this.Utils.sprintf(user.Accounts, userID), inNewTab);
				break;
			case buttons.UserRecentSummary:
				loadURL(consts.Protocol + "://" +
						consts.Host + this.Utils.sprintf(user.Recent, userID), inNewTab);
				break;
			case buttons.UserRecentReputation:
				loadURL(consts.Protocol + "://" +
						consts.Host + this.Utils.sprintf(user.RecentRep, userID), inNewTab);
				break;
			case buttons.UserRecentResponses:
				loadURL(consts.Protocol + "://" +
						consts.Host + this.Utils.sprintf(user.Responses, userID), inNewTab);
				break;
			case buttons.UserRecentRevisions:
				loadURL(consts.Protocol + "://" +
						consts.Host + this.Utils.sprintf(user.Revisions, userID), inNewTab);
				break;
			case buttons.UserRecentBadges:
				loadURL(consts.Protocol + "://" +
						consts.Host + this.Utils.sprintf(user.Badges, userID), inNewTab);
				break;
			case buttons.ShowOptions:
				this.Utils.ShowOptions();
				break;
			case buttons.ShowOverview:
				this.Utils.ShowOverview();
				break;
		}
	},
	PrepareContextSearch: function (event, search) {
		this.Utils.Log('Entering PrepareContextSearch');
		// ****************************************
		// Step 1: Get the selected text
		// ****************************************
	
		var node = document.popupNode;
		var selection = "";
		var nodeLocalName = node.localName.toLowerCase();
	
		if((nodeLocalName == "textarea") || (nodeLocalName == "input" && node.type == "text"))
			selection = node.value.substring(node.selectionStart, node.selectionEnd);
		else
		{
			var focusedWindow = document.commandDispatcher.focusedWindow;
			selection = focusedWindow.getSelection().toString();
		}
	
		// Limit the selection length
		if(selection.length >= 150)
			selection = selection.substring(0, 149);
	
		// ****************************************
		// Step 2: Clean up the selected text
		// ****************************************
	
		selection = this.Utils.TrimString(selection); // Clean up whitespace
		
		var selArray = selection.split(" ");
		for(var i=0; i<selArray.length; i++)
		{
			selArray[i] = selArray[i].replace(/^(\&|\(|\)|\[|\]|\{|\}|\"|,|\.|!|\?|'|:|;)+/, "");
			selArray[i] = selArray[i].replace(/(\&|\(|\)|\[|\]|\{|\}|\"|,|\.|!|\?|'|:|;)+$/, "");
		}
	
		selection = selArray.join(" ");
	
		// ****************************************
		// Step 3: Update the search box
		// ****************************************
	
		this.SetTerms(selection);
	
		// ****************************************
		// Step 4: Perform the search
		// ****************************************
	
		this.Search(event, search);
	},
	UpdateContextMenuVisibility: function () {
		this.Utils.Log('Entering UpdateContextMenuVisibility');
		//Todo
	},
	UpdateContextMenu: function () {
		this.Utils.Log('Entering UpdateContextMenu');
		var contextMenu = document.getElementById('SOB-Context');
		var node = document.popupNode;
		var selection = "";
		var nodeLocalName = node.localName.toLowerCase();
		if((nodeLocalName == "textarea") || (nodeLocalName == "input" && node.type == "text"))
			selection = node.value.substring(node.selectionStart, node.selectionEnd);
		else
		{
			var focusedWindow = document.commandDispatcher.focusedWindow;
			selection = focusedWindow.getSelection().toString();
		}
		this.Utils.Log('Selection: ' + selection);
		if (selection.length == 0) {
			contextMenu.setAttribute('disabled', 'true');
		} else {
			contextMenu.setAttribute('disabled', 'false');
		}
		return true;
	},
	ProgressListener: function () {
		this.Utils.Log('Entering ProgressListener');
		//Todo
	},
	Init: function() {
		this.Utils.Log('Entering Init');
		
		this.Utils.Log('Importing Preferences.jsm');
		try {
			Components.utils.import("resource://stackoverflowbar/Preferences.jsm", org.gcarreno.StackOverflowBar);
			this.Utils.Log("Module Preferences imported");
		} catch(e) {
			this.Utils.Log("Error: " + e.message);
		}

		org.gcarreno.jSapiens.init();
		this.Database.init();
		this.Overview.init();
		this.Timeline.my_turn();
		
		var mainItem = document.getElementById("SOB-Main-Item");
		// Only initialize if the main toolbar item is present
		if(mainItem)
		{
			this._first_run = this.Utils.GetOption('first_run', 'bool');
			if (this._first_run) {
				this.Utils.Log('First run');
				this.Utils.SetOption('first_run', 'bool', false);
				this.Database.CreateDB()
			}
			this.UpdateContextMenuVisibility(); // Todo
		}
	},
	Finalise: function () {
		this.Utils.Log('Entering Finalise');
		//if (typeof window.getBrowser != 'undefined') {
		//	window.getBrowser().removeProgressListener(this.ProgressListener);
		//}
	},
	Database: {
		_sobU: null,
		_file: "sob-database.db",
		_dirS: Components.classes["@mozilla.org/file/directory_service;1"]
				.getService(Components.interfaces.nsIProperties),
		_dir: null,
		
		_storage: Components.classes["@mozilla.org/storage/service;1"]
				.getService(Components.interfaces.mozIStorageService),
				  
		_console: Components.classes['@mozilla.org/consoleservice;1']
				.getService(Components.interfaces.nsIConsoleService),
				
		_dbConn: null,
		
		init: function() {
			this.Log('Entering init');
			try {
				this.Log('File: ' + this._file);
				this._dir = this._dirS.get("ProfD", Components.interfaces.nsIFile);
				this._dir.append("StackOverflowBar");
			} catch(e) {
				this.Log('Error: ' +e.message);
			}
			if (!this._dir.exists() || !this._dir.isDirectory) {
				this.Log('Folder does not exist, creating');
				this._dir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0774);
			}
			try {
				this._dir.append(this._file);
			} catch(e) {
				this.Log('Error: ' +e.message);
			}
			if (!this._dir.exists()) {
				this.Log('File missing, will create on DB Connect');
			}
			try {
				this._dbConn =this._storage.openDatabase(this._dir);
			} catch(e) {
				this.Log('Error: ' +e.message);
			}
		},
		
		CreateDB: function() {
			this.Log('Creating Database');
			this._dbConn.executeSimpleSQL("CREATE TABLE timeline (date INTEGER, type STRING)");
		},
	
		Log: function (aMessage) {
			this._console.logStringMessage('StackOverflowBar.Database: ' + aMessage);
		}
	},
	Timeline: {
		_console: Components.classes['@mozilla.org/consoleservice;1']
				.getService(Components.interfaces.nsIConsoleService),
		Log: function(aMessage) {
			this._console.logStringMessage('StackOverflowBar.Timeline: ' + aMessage);
		},
		my_turn: function() {
			return;
			var timeout = org.gcarreno.StackOverflowBar.Utils.GetOption('timeout');
			window.setTimeout(function() {
				org.gcarreno.StackOverflowBar.Timeline.my_turn();
			}, timeout * 60 * 1000);
		}
	},
	Overview : {
		_sob: null,
		_sobU: null,
		_sobD: null,
		_jSapiens: null,
		_console: Components.classes['@mozilla.org/consoleservice;1']
				.getService(Components.interfaces.nsIConsoleService),
		
		init: function(){
			this.Log('init');
			if (typeof org.gcarreno.StackOverflowBar != 'undefined') {
				this.Log('Can reach SOB');
				this._sob = org.gcarreno.StackOverflowBar;
			}
			if (typeof org.gcarreno.StackOverflowBar.Database != 'undefined') {
				this.Log('Can reach SOB.D');
				this._sobD = org.gcarreno.StackOverflowBar.Database;
			}
			if (typeof org.gcarreno.StackOverflowBar.Utils != 'undefined') {
				this.Log('Can reach SOB.U');
				this._sobU = org.gcarreno.StackOverflowBar.Utils;
			}
			if (typeof org.gcarreno.jSapiens != 'undefined') {
				this.Log('Can reach jSapiens');
				this._jSapiens = org.gcarreno.jSapiens;
			}
		},
		
		refresh: function () {
			var contents = document.getElementById('SOB-overview-contents');
			
			var api_answer = this._jSapiens.users.timeline(this._sobU.GetOption('user_id'));
			var b_value = '';
			
			b_value += 'User Timeline:\n';
			b_value += '\tTotal: ' + api_answer.total + '\n';
			
			if (api_answer.total > 0) {
				for (var x = 0; x < api_answer.user_timelines.length; x++) {
					b_value += '\t\tUser: ' + api_answer.user_timelines[x].user_id + '\n';
					b_value += '\t\t\ttype: ' + api_answer.user_timelines[x].timeline_type + '\n';
					switch (api_answer.user_timelines[x].timeline_type) {
						case "comment":
							b_value += '\t\t\taction: ' + api_answer.user_timelines[x].action + '\n';
							b_value += '\t\t\tdescription: ' + api_answer.user_timelines[x].description + '\n';
							b_value += '\t\t\tdetail: ' + api_answer.user_timelines[x].detail + '\n';
							break;
						case "revision":
							b_value += '\t\t\taction: ' + api_answer.user_timelines[x].action + '\n';
							b_value += '\t\t\tdescription: ' + api_answer.user_timelines[x].description + '\n';
							b_value += '\t\t\tdetail: ' + api_answer.user_timelines[x].detail + '\n';
							break;
						case "badge":
							b_value += '\t\t\taction: ' + api_answer.user_timelines[x].action + '\n';
							b_value += '\t\t\tdescription: ' + api_answer.user_timelines[x].description + '\n';
							b_value += '\t\t\tdetail: ' + api_answer.user_timelines[x].detail + '\n';
							break;
						case "accepted":
							b_value += '\t\t\taction: ' + api_answer.user_timelines[x].action + '\n';
							b_value += '\t\t\tdescription: ' + api_answer.user_timelines[x].description + '\n';
							break;
						case "askoranswered":
							b_value += '\t\t\taction: ' + api_answer.user_timelines[x].action + '\n';
							b_value += '\t\t\tdescription: ' + api_answer.user_timelines[x].description + '\n';
							break;
					}
					var creation_date = new Date(api_answer.user_timelines[x].creation_date * 1000);
					b_value += '\t\t\tDate: ' + creation_date + '\n';
					//b_value += '\t\t\tviews: ' + api_answer.user_timelines[x].view_count + '\n';
				}
			}
			
			contents.value = b_value;
		},
		
		Log: function (aMessage) {
			this._console.logStringMessage('StackOverflowBar.Overview: ' + aMessage);
		}
	},
	Utils: {
		consoleService: Components.classes['@mozilla.org/consoleservice;1']
						.getService(Components.interfaces.nsIConsoleService),
		prefService: Components.classes["@mozilla.org/preferences-service;1"]
						.getService(Components.interfaces.nsIPrefService),
						
		_sob_prefs: null,
		
		Log: function (aMessage) {
			this.consoleService.logStringMessage('StackOverflowBar: ' + aMessage);
		},
		GetOption: function(optName, optType) {
			if (this._sob_prefs == null) {
				this._sob_prefs = new org.gcarreno.StackOverflowBar.Preferences("extensions.stackoverflowbar.");
			}
			var result = this._sob_prefs.get(optName);
			
			this.Log('Prefs get: ' + optName + ': '+ result);

			return result;
		},
		SetOption: function(optName, optType, optValue) {
			if (this._sob_prefs == null) {
				this._sob_prefs = new org.gcarreno.StackOverflowBar.Preferences("extensions.stackoverflowbar.");
			}
			this.Log('Prefs set: ' + optName + ': '+ optValue);

			this._sob_prefs.set(optName, optValue);
		},
		LoadOptions: function () {
			const options = org.gcarreno.StackOverflowBar.Strings.Options;
			
			document.getElementById("SOB-Opt-SearchInTab").checked = 
				this.GetOption(options.SearchInTab, "bool");
			document.getElementById("SOB-Opt-ButtonsInTab").checked = 
				this.GetOption(options.ButtonsInTab, "bool");
				
			//document.getElementById("SOB-Opt-UseAPI").checked =
			//    this.GetOption(options.UseAPI, "bool");
				
			document.getElementById("SOB-Opt-UserID").value =
				this.GetOption(options.UserID, "string");
		},
		SaveOptions: function () {
			const options = org.gcarreno.StackOverflowBar.Strings.Options;

			this.SetOption(options.SearchInTab, "bool", 
				document.getElementById("SOB-Opt-SearchInTab").checked);
			this.SetOption(options.ButtonsInTab, "bool",
				document.getElementById("SOB-Opt-ButtonsInTab").checked);
				
			//this.SetOption(options.UseAPI, "bool",
			//    document.getElementById("SOB-Opt-UseAPI").checked);
			
			this.SetOption(options.UserID, "string",
				document.getElementById("SOB-Opt-UserID").value);
		},
		ShowOptions: function () {
			var flags = "chrome,centerscreen,modal";
			window.openDialog("chrome://stackoverflowbar/content/options.xul", "&sobar.options.title;", flags);
		},
		ShowOverview: function () {
			var flags = "chrome,centerscreen,resizable";
			window.openDialog("chrome://stackoverflowbar/content/overview.xul", "&sobar.overview.title;", flags);
		},
		LoadURL: function (aURL, inNewTab) {
			if(inNewTab)
			{
				var browser = window.getBrowser();
				var newTab = browser.addTab(aURL);
				browser.selectedTab = newTab;
			}
			else
			{
				var content = window.content;
				content.document.location = aURL;
				content.focus();
			}
		},
		LoadHomepage: function (event) {
			const options = org.gcarreno.StackOverflowBar.Strings.Options;
			const consts = org.gcarreno.StackOverflowBar.Strings.Constants;
			
			var inNewTab = this.GetOption(options.ButtonsInTab, "bool");
			var URL = consts.Protocol + "://" + consts.Host;
			this.LoadURL(URL, inNewTab);
			event.stopPropagation();
		},
		LoadAboutURL: function (aWhere) {
			var url = "";
			switch(aWhere) {
				case 'home':
					url = 'http://guscarreno.blogspot.com/p/stack-overflow-bar.html'
					break;
				case 'support':
					url = 'http://www.assembla.com/spaces/StackOverflowBar'
					break;
			}
			
			var windowService = Components.classes["@mozilla.org/appshell/window-mediator;1"]
								.getService(Components.interfaces.nsIWindowMediator);
			var currentWindow = windowService.getMostRecentWindow("navigator:browser");
		
			if(currentWindow)
			{
				try {
					currentWindow.delayedOpenTab(url);
				} catch(e) {
					currentWindow.loadURI(url);
				}
			}
			else
				window.open(url);
		},
		TrimString: function (string) {
			if (!string) {
				return "";
				}
			string = string.replace(/^\s+/, '');
			string = string.replace(/\s+$/, '');
			string = string.replace(/\s+/g, ' ');
			return string;
		},
		ConvertTermsToURI: function (terms) {
			var termArray = new Array();
			termArray = terms.split(" ");
			var result = "";
			for (var i = 0; i < termArray.length; i++) {
				if (i > 0) {
					result += "+";
				}
				result += encodeURIComponent(termArray[i]);
			}
			return result;
		},
		DoNothing: function () {},
/**
* sprintf() for JavaScript v.0.4
*
* Copyright (c) 2007 Alexandru Marasteanu <http://alexei.417.ro/>
* Thanks to David Baird (unit test and patch).
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
		str_repeat: function (i, m) {
			for (var o = []; m > 0; o[--m] = i); return(o.join('')); 
		},
		sprintf: function () {
			var i = 0, a, f = arguments[i++], o = [], m, p, c, x;
			while (f) {
			  if (m = /^[^\x25]+/.exec(f)) o.push(m[0]);
			  else if (m = /^\x25{2}/.exec(f)) o.push('%');
			  else if (m = /^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f)) {
				if (((a = arguments[m[1] || i++]) == null) || (a == undefined)) throw("Too few arguments.");
				if (/[^s]/.test(m[7]) && (typeof(a) != 'number'))
				  throw("Expecting number but found " + typeof(a));
				switch (m[7]) {
				  case 'b': a = a.toString(2); break;
				  case 'c': a = String.fromCharCode(a); break;
				  case 'd': a = parseInt(a); break;
				  case 'e': a = m[6] ? a.toExponential(m[6]) : a.toExponential(); break;
				  case 'f': a = m[6] ? parseFloat(a).toFixed(m[6]) : parseFloat(a); break;
				  case 'o': a = a.toString(8); break;
				  case 's': a = ((a = String(a)) && m[6] ? a.substring(0, m[6]) : a); break;
				  case 'u': a = Math.abs(a); break;
				  case 'x': a = a.toString(16); break;
				  case 'X': a = a.toString(16).toUpperCase(); break;
				}
				a = (/[def]/.test(m[7]) && m[2] && a > 0 ? '+' + a : a);
				c = m[3] ? m[3] == '0' ? '0' : m[3].charAt(1) : ' ';
				x = m[5] - String(a).length;
				p = m[5] ? this.str_repeat(c, x) : '';
				o.push(m[4] ? a + p : p + a);
			  }
			  else throw ("Huh ?!");
			  f = f.substring(m[0].length);
			}
			return o.join('');
		}
	}
}

window.addEventListener("load",   function () {return org.gcarreno.StackOverflowBar.Init(); }     , false);
window.addEventListener("unload", function () {return org.gcarreno.StackOverflowBar.Finalise(); } , false);
